package com.alien.admin.modules.quartz.task;

import com.alien.admin.modules.container.domain.K8sDeploymentStatus;
import com.alien.admin.modules.container.domain.K8sPodMetricStatus;
import com.alien.admin.modules.container.repository.K8sDeploymentStatusRepository;
import com.alien.admin.modules.container.service.K8sDeploymentStatusService;
import com.alien.admin.modules.container.service.K8sPodMetricStatusHistoryService;
import com.alien.admin.modules.container.service.K8sPodMetricStatusService;
import com.alien.admin.modules.deploy.domain.DpK8sInstance;
import com.alien.admin.modules.deploy.repository.DpK8sInstanceRepository;
import com.alien.admin.modules.basic.domain.Deployment;
import com.alien.admin.modules.basic.domain.PodMetric;
import com.alien.admin.modules.basic.service.K8sService;
import com.alien.admin.utils.DateUtil;
import com.alien.admin.utils.DeployConstant;
import com.alien.admin.utils.RedisLockUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 集群状态监测
 */
@Slf4j
@Component
public class ContainerStatusTask {

    @Autowired
    private DpK8sInstanceRepository dpK8sInstanceRepository;
    @Autowired
    private K8sDeploymentStatusRepository k8sDeploymentStatusRepository;
    @Autowired
    private K8sService k8sService;
    @Autowired
    private K8sDeploymentStatusService k8sDeploymentStatusService;
    @Autowired
    private K8sPodMetricStatusService k8sPodMetricStatusService;
    @Autowired
    private K8sPodMetricStatusHistoryService k8sPodMetricStatusHistoryService;
    @Autowired
    private RedisLockUtil redisLockUtil;

    public void queryK8sDeploymentStatus(DpK8sInstance dpK8sInstance, String namepace) {
        Integer k8sId = dpK8sInstance.getId();
        List<Deployment> deploymentList = k8sService.getDeployments(dpK8sInstance, namepace);

        List<K8sDeploymentStatus> k8sDeploymentStatuses = deploymentList.stream().map(deployment -> {
            K8sDeploymentStatus k8sDeploymentStatus = new K8sDeploymentStatus();
            k8sDeploymentStatus.setK8sId(k8sId);
            k8sDeploymentStatus.setNamespace(namepace);
            k8sDeploymentStatus.setDeploymentName(deployment.getName());

            Deployment.DeploymentStatus status = deployment.getStatus();
            k8sDeploymentStatus.setAvailableReplicas(status.getAvailableReplicas());
            k8sDeploymentStatus.setReadyReplicas(status.getReadyReplicas());
            k8sDeploymentStatus.setReplicas(status.getReplicas());
            k8sDeploymentStatus.setUpdatedReplicas(status.getUpdatedReplicas());

            Deployment.DeploymentResource resource = deployment.getDeploymentResource();
            if(resource != null) {
                k8sDeploymentStatus.setLimitCpu(resource.getLimitCpu());
                k8sDeploymentStatus.setLimitMem(resource.getLimitMem());
                k8sDeploymentStatus.setRequestCpu(resource.getRequestCpu());
                k8sDeploymentStatus.setRequestMem(resource.getRequestMem());
            }
            return k8sDeploymentStatus;
        }).collect(Collectors.toList());
        k8sDeploymentStatusService.deleteK8sDeploymentStatus(k8sId, namepace);
        k8sDeploymentStatusRepository.saveAll(k8sDeploymentStatuses);
    }

    public void queryDeploymentStatus() {
        /** 分布式锁的key */
        String lockKey = "ContainerStatusTask_queryDeploymentStatus";
        if(redisLockUtil.tryLock(lockKey, 60L)) {
            queryK8sBaseDataStatus((dpK8sInstance, namespace) -> {
                queryK8sDeploymentStatus(dpK8sInstance, namespace);
            });
        }
    }

    public void queryPodMetricStatus() {
        /** 分布式锁的key */
        String lockKey = "ContainerStatusTask_queryPodMetricStatus";
        if(redisLockUtil.tryLock(lockKey, 60L)) {
            queryK8sBaseDataStatus((dpK8sInstance, namespace) -> {
                queryK8sDataStatus(dpK8sInstance, namespace);
            });
        }
    }

    public void clearPodMetricsHistory(String daysStr) {
        /** 分布式锁的key */
        String lockKey = "ContainerStatusTask_clearPodMetricsHistory";
        if(redisLockUtil.tryLock(lockKey, 60L)) {
            Integer days = StringUtils.isEmpty(daysStr) ? 3 : Integer.valueOf(daysStr);
            // 清除过期的数据
            k8sPodMetricStatusHistoryService.clearHistoryData(days);
        }
    }

    private K8sPodMetricStatus generateSumK8sPodMetricsStatus(List<K8sPodMetricStatus> k8sPodMetricStatusList, Integer k8sId, String namespace, Long minute) {
        K8sPodMetricStatus k8sPodMetricStatus = new K8sPodMetricStatus();
        k8sPodMetricStatus.setK8sId(k8sId);
        k8sPodMetricStatus.setNamespace(namespace);
        k8sPodMetricStatus.setMinute(minute);

        Double sumCpu = k8sPodMetricStatusList.stream().mapToDouble(K8sPodMetricStatus::getCpu).sum();
        Long sumMem = k8sPodMetricStatusList.stream().mapToLong(K8sPodMetricStatus::getMem).sum();
        k8sPodMetricStatus.setCpu(sumCpu);
        k8sPodMetricStatus.setMem(sumMem);

        k8sPodMetricStatus.setPodName(DeployConstant.K8S_SUM_NAME);
        k8sPodMetricStatus.setDeploymentName(DeployConstant.K8S_SUM_NAME);

        return k8sPodMetricStatus;
    }

    public void queryK8sDataStatus(DpK8sInstance dpK8sInstance, String namespace) {
        Integer k8sId = dpK8sInstance.getId();
        List<PodMetric> podMetricList = k8sService.getPodMetrics(dpK8sInstance, namespace);

        Long minute = DateUtil.getCurrentMinute();

        List<K8sPodMetricStatus> k8sPodMetricStatusList = podMetricList.stream().map(podMetric -> {
            String podName = podMetric.getPodName();
            // szy-51110-server-deployment-789cf4c9ff-vfckk
            int index = podName.indexOf("-deployment");
            String projectName = index > -1 ? podName.substring(0, index) : podName;

            K8sPodMetricStatus k8sPodMetricStatus = new K8sPodMetricStatus();
            k8sPodMetricStatus.setK8sId(k8sId);
            k8sPodMetricStatus.setNamespace(namespace);
            k8sPodMetricStatus.setMinute(minute);
            k8sPodMetricStatus.setPodName(podName);
            k8sPodMetricStatus.setDeploymentName(String.format("%s-deployment", projectName));
            k8sPodMetricStatus.setCpu(podMetric.getCpu());
            k8sPodMetricStatus.setMem(podMetric.getMem());
            return k8sPodMetricStatus;
        }).collect(Collectors.toList());

        // 添加1条集群的数据汇总记录
        K8sPodMetricStatus sumPodMetricStatus = generateSumK8sPodMetricsStatus(k8sPodMetricStatusList, k8sId, namespace, minute);
        k8sPodMetricStatusList.add(sumPodMetricStatus);

        k8sPodMetricStatusService.discardK8sPodMetricStatus(k8sId, namespace);
        k8sPodMetricStatusService.batchSave(k8sPodMetricStatusList);
    }

    public void queryK8sBaseDataStatus(K8sDataStatusQuery query) {
        List<DpK8sInstance> k8sInstanceList = dpK8sInstanceRepository.findAll();
        k8sInstanceList.stream().forEach(dpK8sInstance -> {
            String namespaceListStr = dpK8sInstance.getNamespaceList();
            if(StringUtils.isNotBlank(namespaceListStr)) {
                String[] namespaceList = namespaceListStr.split(",");
                for(String namespace : namespaceList) {
                    query.queryK8sDataStatus(dpK8sInstance, namespace);
                }
            }
        });
    }

    public interface K8sDataStatusQuery {
        void queryK8sDataStatus(DpK8sInstance dpK8sInstance, String namespace);
    }
}
